package com.xue;

import com.xue.domain.Info;
import com.xue.handler.AreaInfoHandler;
import com.xue.handler.LocationInfoHandler;
import com.xue.handler.StaticLocationResponseInfoHandler;
import com.xue.handler.UdpServerHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;

/**
 * udp连接部分
 *
 * @author xue
 * @create 2022-09-16 17:02
 */
@Slf4j
public class UdpConnect {

    private static EventLoopGroup group;

    public static final String SAND_TABLE_IP = "192.168.1.100";
    public static final Integer SAND_TABLE_PORT = 1693;
    public static final InetSocketAddress ADDRESS = new InetSocketAddress(UdpConnect.SAND_TABLE_IP, UdpConnect.SAND_TABLE_PORT);

    private static Channel channel;

    public static void init() throws InterruptedException {
        group = new NioEventLoopGroup(2);
        Bootstrap bootstrap = new Bootstrap();
        UdpServerHandler udpServerHandler = new UdpServerHandler();
        LocationInfoHandler locationInfoHandler = new LocationInfoHandler();
        StaticLocationResponseInfoHandler staticLocationResponseInfoHandler = new StaticLocationResponseInfoHandler();
        AreaInfoHandler areaInfoHandler = new AreaInfoHandler();
        bootstrap.group(group)
                // 主线程处理
                .channel(NioDatagramChannel.class)
                // 广播
                .option(ChannelOption.SO_BROADCAST, true)
                // 设置udp单帧超过2M的办法
                //.option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(65535))
                // 设置读缓冲区为2M
                .option(ChannelOption.SO_RCVBUF, 2048 * 1024)
                // 设置写缓冲区为1M
                .option(ChannelOption.SO_SNDBUF, 1024 * 1024)
                .handler(new ChannelInitializer<NioDatagramChannel>() {

                    @Override
                    protected void initChannel(NioDatagramChannel ch) {
                        ChannelPipeline pipeline = ch.pipeline();
                        pipeline.addLast(udpServerHandler);
                        pipeline.addLast(locationInfoHandler);
                        pipeline.addLast(areaInfoHandler);
                        pipeline.addLast(staticLocationResponseInfoHandler);
                    }
                });
        ChannelFuture f = bootstrap.bind(7777).sync();
        channel = f.channel();
        log.info("7777端口监听启动……");
        channel.closeFuture().addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture channelFuture) throws Exception {
                log.info("7777端口已关闭……");
            }
        });
    }

    public static void sendInfo(Info info) {
        if (channel != null && channel.isActive()) {
            ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();
            channel.writeAndFlush(new DatagramPacket(info.encoding(byteBuf), ADDRESS));
        }
    }

    public static void stop() {
        group.shutdownGracefully();
    }

}
